defmodule SockWorkstation.CoopMgrGen do
  use GenServer

  # @name __MODULE__

  @keepalive_interval 30_000

  # defmodule CoopState do
  defstruct topus_pid: nil,
            topcm_pid: nil,
            coop_pid: nil,
            coop_mgr_pid: nil,
            llm_pid: nil,
            nif_pid: nil,
            asr_helper_pid: nil,
            tts_helper_pid: nil,
            membrane_source_pid: nil,
            is_inited?: false,
            coop_type: :chat,
            # inter_peer: nil,
            coop_status: nil,
            coop_autolisten?: false,
            coop_vol: 0,
            # tts_task_id: "",
            # asr_task_id: "",
            user_id: nil,
            session_id: nil

  # end
  alias SockWorkstation.CoopMgrGen

  alias SockWorkstation.{
    #   # ASRHelperGen,
    CtrlMgrGen,
    SockCoopClient,
    FrameHelperGen
    # PingPongGen
    # SessionMgr
    # TTSHelperGen,
    #   # OpusCodec,
    # CoopHelperSup
    #   # OpusCodecSup
  }

  # Client API

  def start_link(session_id) do
    GenServer.start_link(CoopMgrGen, session_id, name: via_tuple(session_id, "coop"))
    #  {:ok,  session_id}
  end

  def get_state(session_id) do
    GenServer.call(via_tuple(session_id, "coop"), :get_state)
  end

  def get_sessid(session_id) do
    GenServer.call(via_tuple(session_id, "coop"), :get_sessid)
  end

  # def update_state(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :update_state)
  # end

  # Server Callbacks

  @impl true
  def init(session_id) do
    self_pid = self()
    # session_id = "c87e77dd"
    # start_codec(session_id)
    # start_nif_codec(session_id)
    # start_asr_helper(session_id)
    # start_tts_helper(session_id)
    # start_frame_queue(session_id)
    # start_vad_client(session_id)
    # start_llm_client(session_id)
    schedule_keepalive()
    # start_coop_client(session_id)
    # send(self_pid, {:run_coop_client, session_id})

    IO.puts("CoopMgrGen started")
    # send(self_pid, :run_nif_codec)
    # send(self_pid, :run_asr_helper)

    state = %CoopMgrGen{
      # is_inited?: true,
      session_id: session_id,
      # user_id: user_id,
      coop_mgr_pid: self_pid
    }

    # send(self_pid, :run_codec)
    {:ok, state}
  end

  def fetch_coop_pid(session_id, pid) do
    GenServer.cast(via_tuple(session_id, "coop"), {:fetch_coop_pid, pid})
  end

  # def rm_coop_pid(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :rm_coop_pid)
  # end

  def rm_session_id(session_id) do
    GenServer.cast(via_tuple(session_id, "coop"), :rm_session_id)
  end

  # def add_asr_pid(session_id, pid) do
  #   GenServer.cast(via_tuple(session_id, "coop"), {:add_asr_pid, pid})
  # end

  def runfirst_for_uid(session_id, user_id) do
    GenServer.cast(via_tuple(session_id, "coop"), {:runfirst_for_uid, user_id})
  end

  def fetch_asr_helper_pid(session_id, pid) do
    GenServer.cast(via_tuple(session_id, "coop"), {:fetch_asr_helper_pid, pid})
  end

  # def rm_asr_helper_pid(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :rm_asr_helper_pid)
  # end

  def fetch_tts_helper_pid(session_id, pid) do
    GenServer.cast(via_tuple(session_id, "coop"), {:fetch_tts_helper_pid, pid})
  end

  # def rm_tts_helper_pid(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :rm_tts_helper_pid)
  # end

  def fetch_llm_pid(session_id, pid) do
    GenServer.cast(via_tuple(session_id, "coop"), {:fetch_llm_pid, pid})
  end

  # def rm_llm_pid(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :rm_llm_pid)
  # end

  def fetch_membrane_source_pid(session_id, pid) do
    GenServer.cast(via_tuple(session_id, "coop"), {:fetch_membrane_source_pid, pid})
  end

  # def rm_membrane_source_pid(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :rm_membrane_source_pid)
  # end

  def fetch_topus_pid(session_id, pid) do
    GenServer.cast(via_tuple(session_id, "coop"), {:fetch_topus_pid, pid})
  end

  # def rm_topus_pid(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :rm_topus_pid)
  # end

  def fetch_topcm_pid(session_id, pid) do
    GenServer.cast(via_tuple(session_id, "coop"), {:fetch_topcm_pid, pid})
  end

  # def rm_topcm_pid(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :rm_topcm_pid)
  # end

  def fetch_nif_pid(session_id, pid) do
    GenServer.cast(via_tuple(session_id, "coop"), {:fetch_nif_pid, pid})
  end

  # def rm_nif_pid(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :rm_nif_pid)
  # end

  # def start_nif_codec(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :run_nif_codec)
  # end

  # def start_codec(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :run_codec)
  # end

  # def start_asr_helper(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :run_asr_helper)
  # end

  # def start_tts_helper(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :run_tts_helper)
  # end

  # def start_coop_client(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :run_coop_client)
  # end

  # def start_frame_queue(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :run_frame_queue)
  # end

  # def start_llm_client(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :run_llm_client)
  # end

  # def start_vad_client(session_id) do
  #   GenServer.cast(via_tuple(session_id, "coop"), :run_vad_client)
  # end

  def start_speaking(session_id) do
    GenServer.cast(via_tuple(session_id, "coop"), :start_speaking)
    # coop_pid=get_state(session_id).coop_pid
    # SockCoopClient.send_speaking(coop_pid)
  end

  def start_listening(session_id) do
    GenServer.cast(via_tuple(session_id, "coop"), :start_listening)
    # coop_pid=get_state(session_id).coop_pid
    # SockCoopClient.send_listening(coop_pid)
  end

  def start_listened(session_id) do
    GenServer.cast(via_tuple(session_id, "coop"), :start_listened)
    # coop_pid=get_state(session_id).coop_pid
    # SockCoopClient.send_listening(coop_pid)
  end

  def stop_listened(session_id) do
    GenServer.cast(via_tuple(session_id, "coop"), :stop_listened)
    # coop_pid=get_state(session_id).coop_pid
    # SockCoopClient.send_listening(coop_pid)
  end

  def prep_intercom(session_id, fr_sessid, to_sessid) do
    GenServer.call(
      via_tuple(session_id, "coop"),
      {:prep_intercom, fr_sessid, to_sessid}
    )
  end

  def unprep_intercom(session_id, fr_sessid, to_sessid) do
    GenServer.call(
      via_tuple(session_id, "coop"),
      {:unprep_intercom, fr_sessid, to_sessid}
    )
  end

  # def start_inter_com(session_id, fr_sessid, to_sessid) do
  #   GenServer.cast(via_tuple(session_id, "coop"), {:start_inter_com, {fr_sessid, to_sessid}})
  # end

  # def stop_intercom(session_id, fr_sessid, to_sessid) do
  #   GenServer.cast(via_tuple(session_id, "coop"), {:stop_intercom, {fr_sessid, to_sessid}})
  # end

  def set_volume(session_id, num) do
    # coop_pid = get_state(session_id).coop_pid
    # SockCoopClient.set_volume(coop_pid, num)
    GenServer.cast(via_tuple(session_id, "coop"), {:set_volume, num})
  end

  def toggle_speaking(session_id) do
    GenServer.cast(via_tuple(session_id, "coop"), :toggle_speaking)
  end

  def toggle_listening(session_id) do
    GenServer.cast(via_tuple(session_id, "coop"), :toggle_listening)
  end

  def toggle_autolisten(session_id) do
    GenServer.cast(via_tuple(session_id, "coop"), :toggle_autolisten)
  end

  def toggle_not_autolisten(session_id) do
    GenServer.cast(via_tuple(session_id, "coop"), :toggle_not_autolisten)
  end


  def say_goodbye(session_id) do
    GenServer.cast(via_tuple(session_id, "coop"), :say_goodbye)
  end

  def run_asr_result(session_id, result) do
    GenServer.cast(via_tuple(session_id, "coop"), {:asr_result, result})
  end

  def run_tts_result(session_id) do
    GenServer.cast(via_tuple(session_id, "coop"), :tts_result)
  end

  def run_test_opus(session_id) do
    send(SockWorkstation.CoopMgrGen.get_state(session_id).tts_helper_pid, :test_opus)
  end

  @impl true
  def handle_call(:get_state, _from, state) do
    # state = %CoopMgrGen{state | is_inited?: false}
    {:reply, state, state}
  end

  def handle_call(:get_sessid, _from, state) do
    # state = %CoopMgrGen{state | is_inited?: false}
    {:reply, {:ok, state.session_id}, state}
  end

  def handle_call({:prep_intercom, fr_sessid, to_sessid}, _from, state) do
    with {:ok, _to_sessid} = get_sessid(to_sessid) do
      toggle_speaking(fr_sessid)
      toggle_speaking(to_sessid)
      IO.puts("Prepare intercom #{fr_sessid} to #{to_sessid}")

      state =
        state
        |> Map.put(:coop_type, :inter_com)
        |> Map.put(:inter_peer, {fr_sessid, to_sessid})

      {:reply, {:ok, state.coop_pid}, state}
    end
  end

  def handle_call({:unprep_intercom, fr_sessid, to_sessid}, _from, state) do
    # with {:ok, _to_sessid} = get_sessid(to_sessid) do
    toggle_speaking(fr_sessid)
    toggle_speaking(to_sessid)
    IO.puts("Unprepare intercom #{fr_sessid} to #{to_sessid}")

    state =
      state
      |> Map.put(:coop_type, :chat)
      |> Map.put(:inter_peer, nil)

    {:reply, {:ok, state.coop_pid}, state}
    # end
  end

  @impl true
  # def handle_cast(:update_state, state) do
  #   coop_pid = state.coop_pid
  #   is_pid(coop_pid) || Process.alive?(coop_pid) || send(coop_pid, {:run_add_coop, coop_pid})
  #   state = %CoopMgrGen{state | is_inited?: false}
  #   {:noreply, state}
  # end

  # def handle_cast(:rm_session_id, state) do
  #   {:noreply, %CoopMgrGen{state | session_id: nil}}
  # end

  def handle_cast({:fetch_topus_pid, pid}, state) do
    {:noreply, %CoopMgrGen{state | topus_pid: pid}}
  end

  # def handle_cast(:rm_topus_pid, state) do
  #   {:noreply, %CoopMgrGen{state | topus_pid: nil}}
  # end

  def handle_cast({:fetch_topcm_pid, pid}, state) do
    {:noreply, %CoopMgrGen{state | topcm_pid: pid}}
  end

  # def handle_cast(:rm_topcm_pid, state) do
  #   {:noreply, %CoopMgrGen{state | topcm_pid: nil}}
  # end

  def handle_cast({:fetch_nif_pid, pid}, state) do
    {:noreply, %CoopMgrGen{state | nif_pid: pid}}
  end

  # def handle_cast(:rm_nif_pid, state) do
  #   {:noreply, %CoopMgrGen{state | nif_pid: nil}}
  # end

  def handle_cast({:fetch_coop_pid, coop_pid}, state) when coop_pid == state.coop_pid do
    {:noreply, state}
  end

  def handle_cast({:fetch_coop_pid, pid}, state) do
    {:noreply, %CoopMgrGen{state | coop_pid: pid}}
  end

  # def handle_cast(:rm_coop_pid, state) do
  #   {:noreply, %CoopMgrGen{state | coop_pid: nil}}
  # end

  def handle_cast({:fetch_llm_pid, pid}, state) do
    {:noreply, %CoopMgrGen{state | llm_pid: pid}}
  end

  # def handle_cast(:rm_llm_pid, state) do
  #   {:noreply, %CoopMgrGen{state | llm_pid: nil}}
  # end

  def handle_cast({:fetch_membrane_source_pid, pid}, state) do
    {:noreply, %CoopMgrGen{state | membrane_source_pid: pid}}
  end

  # def handle_cast(:rm_membrane_source_pid, state) do
  #   {:noreply, %CoopMgrGen{state | membrane_source_pid: nil}}
  # end

  def handle_cast({:runfirst_for_uid, uid}, state) when is_pid(state.coop_pid) do
    # if not Process.alive?(state.coop_pid) do
    #   SessionMgr.dyn_coop_client(state.session_id)
    #   Process.sleep(500)
    #   # CtrlMgrGen.start_peer_coop(state.session_id, uid)
    # end

    # TTSHelperGen.bcast_rectodb(state.session_id,"greet_authcode",state.session_id,"greet-#{state.session_id}",state.session_id)
    # Process.sleep(200)
    cond do
      is_nil(uid) ->
        Process.send_after(state.tts_helper_pid, :run_bcast_authcode, 200)
        {:noreply, state}

      true ->
        CtrlMgrGen.fetch_uid(state.session_id, uid)
        {:noreply, %CoopMgrGen{state | user_id: uid}}
    end
  end

  # def handle_cast({:runfirst_for_uid, uid}, state) do
  #   if not Process.alive?(state.coop_pid) do
  #     SessionMgr.dyn_coop_client(state.session_id)
  #     Process.sleep(500)

  #     # CtrlMgrGen.start_peer_coop(state.session_id, uid)
  #   end

  #   {:noreply, %CoopMgrGen{state | user_id: uid}}
  # end

  def handle_cast({:fetch_asr_helper_pid, pid}, state) do
    {:noreply, %CoopMgrGen{state | asr_helper_pid: pid}}
  end

  # def handle_cast(:rm_asr_helper_pid, state) do
  #   {:noreply, %CoopMgrGen{state | asr_helper_pid: nil}}
  # end

  def handle_cast({:set_volume, num}, state) do
    # SockCoopClient.set_volume(state.coop_pid, vol)
    # {:noreply, %CoopMgrGen{state | coop_vol: vol}}
    with :ok <- SockCoopClient.set_volume(state.coop_pid, num) do
      # {:noreply, state}
      {:noreply, %CoopMgrGen{state | coop_vol: num}}
    else
      _ ->
        {:noreply, state}
    end
  end

  def handle_cast({:fetch_tts_helper_pid, pid}, state) do
    {:noreply, %CoopMgrGen{state | tts_helper_pid: pid}}
  end

  # def handle_cast(:rm_tts_helper_pid, state) do
  #   {:noreply, %CoopMgrGen{state | tts_helper_pid: nil}}
  # end

  def handle_cast(:start_speaking, state) do
    with :ok <- SockCoopClient.send_speaking(state.coop_pid) do
      # {:noreply, state}
      {:noreply, %CoopMgrGen{state | coop_status: :speak}}
    else
      _ ->
        {:noreply, state}
    end
  end

  def handle_cast(:toggle_speaking, state) do
    case state.coop_status do
      :speak ->
        FrameHelperGen.stop_push(state.session_id)
        # stop_listened(state.session_id)
        {:noreply, state}

      # :listen ->
      #   stop_listened(state.session_id)
      #   Process.sleep(120)
      #   start_speaking(state.session_id)
      #   {:noreply, state}

      # :lstned ->
      #   stop_listened(state.session_id)
      #   Process.sleep(120)
      #   start_speaking(state.session_id)
      #   {:noreply, state}

      _ ->
        # stop_listened(state.session_id)
        # Process.sleep(120)
        start_speaking(state.session_id)
        {:noreply, state}
    end
  end

  def handle_cast(:toggle_listening, state) do
    case state.coop_status do
      :listen ->
        stop_listened(state.session_id)

        # FrameHelperGen.stop_push(state.session_id)
        # start_listening(state.session_id)

        {:noreply, state}

      # :listen ->
      #   # start_listened(state.session_id)
      #   # Process.sleep(120)
      #   # start_speaking(state.session_id)
      #   {:noreply, state}

      _ ->
        # stop_listened(state.session_id)
        FrameHelperGen.stop_push(state.session_id)
        start_listening(state.session_id)

        {:noreply, state}
    end
  end


  def handle_cast(:toggle_autolisten, state) do
    case state.coop_autolisten? do
      false ->
        SockCoopClient.sendcmd_autolisten(state.coop_pid)
        {:noreply, %CoopMgrGen{state | coop_autolisten?: true}} # {:noreply, state}

      _ ->
        {:noreply, state}
    end
  end

  def handle_cast(:toggle_not_autolisten, state) do
    case state.coop_autolisten? do
      true ->
        SockCoopClient.sendcmd_not_autolisten(state.coop_pid)
        {:noreply, %CoopMgrGen{state | coop_autolisten?: false}} # {:noreply, state}

      _ ->
        {:noreply, state}
    end
  end


  def handle_cast(:start_listening, state) do
    # SockCoopClient.send_listening(state.coop_pid, state.session_id)
    # {:noreply, state}
    with :ok <- SockCoopClient.send_listening(state.coop_pid) do
      # {:noreply, state}
      {:noreply, %CoopMgrGen{state | coop_status: :listen}}
    else
      _ ->
        {:noreply, state}
    end
  end

  def handle_cast(:start_listened, state) do
    # SockCoopClient.send_listened(state.coop_pid, state.session_id)
    # {:noreply, state}
    with :ok <- SockCoopClient.send_listened(state.coop_pid) do
      # {:noreply, state}
      {:noreply, %CoopMgrGen{state | coop_status: :lstned}}
    else
      _ ->
        {:noreply, state}
    end
  end

  def handle_cast(:stop_listened, state) do
    # SockCoopClient.send_not_listened(state.coop_pid, state.session_id)
    # {:noreply, state}
    with :ok <- SockCoopClient.send_not_listened(state.coop_pid) do
      # {:noreply, state}
      {:noreply, %CoopMgrGen{state | coop_status: :not_lstned}}
    else
      _ ->
        {:noreply, state}
    end
  end

  def handle_cast(:say_goodbye, state) do
    with :ok <- SockCoopClient.send_goodbye(state.coop_pid) do
      # {:noreply, state}
      {:noreply, %CoopMgrGen{state | coop_status: nil}}
    else
      _ ->
        {:noreply, state}
    end
  end

  # def handle_cast({:prep_intercom, fr_sessid, to_sessid}, state) do
  #   toggle_speaking(fr_sessid)
  #   toggle_speaking(to_sessid)
  #   IO.puts("Prepare intercom #{fr_sessid} to #{to_sessid}")

  #   state =
  #     state
  #     |> Map.put(:coop_type, :inter_com)
  #     |> Map.put(:inter_peer, {fr_sessid, to_sessid})

  #   {:noreply, state}
  # end

  # def handle_cast({:start_inter_com, {fr_sessid, to_sessid}}, state) do
  #   PingPongGen.prep_intercom(fr_sessid, to_sessid)
  #   SockCoopClient.send_start_intercom(state.coop_pid, fr_sessid, to_sessid)
  #   # send(state.tts_helper_pid, {:inter_com, {fr_sessid, to_sessid}})
  #   state =
  #     state
  #     |> Map.put(:coop_type, :inter_com)
  #     |> Map.put(:inter_peer, {fr_sessid, to_sessid})

  #   {:noreply, state}
  # end

  # def handle_cast({:stop_intercom, {fr_sessid, to_sessid}}, state) do
  #   SockCoopClient.send_stop_intercom(state.coop_pid, fr_sessid, to_sessid)
  #   # send(state.tts_helper_pid, :inter_com)
  #   {:noreply, %CoopMgrGen{state | coop_type: :chat}}
  # end

  # def handle_cast(:run_nif_codec, state) do
  #   # Process.sleep(2000)
  #   CoopHelperSup.super_nif_codec(state.session_id)
  #   {:noreply, state}
  # end

  # def handle_cast(:run_codec, state) do
  #   # Process.sleep(2000)
  #   CoopHelperSup.super_pcm_encode(state.session_id)
  #   {:noreply, state}
  # end

  # def handle_cast(:run_asr_helper, state) do
  #   CoopHelperSup.super_asr_helper(state.session_id)

  #   {:noreply, state}
  # end

  # def handle_cast(:run_tts_helper, state) do
  #   CoopHelperSup.super_tts_helper(state.session_id)

  #   {:noreply, state}
  # end

  # def handle_cast(:run_frame_queue, state) do
  #   CoopHelperSup.super_frame_queue(state.session_id)
  #   {:noreply, state}
  # end

  # def handle_cast(:run_vad_client, state) do
  #   CoopHelperSup.super_vad_client(state.session_id)
  #   {:noreply, state}
  # end

  # def handle_cast(:run_llm_client, state) do
  #   CoopHelperSup.super_llm_client(state.session_id)
  #   {:noreply, state}
  # end

  def handle_cast({:asr_result, result}, state) do
    IO.puts("coop Received asr result: #{result}")
    # IO.inspect(state)
    # SockWorkstation.SockASRClient.send_finish_task(state.asr_pid, state.asr_task_id)
    # send(state.asr_helper_pid, :asr_stop)

    # Process.send_after(state.coop_mgr_pid, :asr_stop, 200)
    {:noreply, state}
  end

  # def handle_cast(:run_coop_client, state) do
  #   # SockWorkstation.SockCoopClient.start_link(state.session_id)
  #   CoopHelperSup.super_coop_client(state.session_id)
  #   {:noreply, state}
  # end

  def handle_cast(:tts_result, state) do
    IO.puts("coop mgr Received tts result")
    # IO.inspect(state)
    # SockWorkstation.SockASRClient.send_finish_task(state.asr_pid, state.asr_task_id)
    # send(state.asr_helper_pid, :asr_stop)
    # send(state.tts_helper_pid, :test_opus)
    # Process.send_after(state.coop_mgr_pid, :asr_stop, 200)
    {:noreply, state}
  end

  @impl true
  # def handle_info({:run_coop_client, session_id}, state) do
  #   SockWorkstation.SockCoopClient.start_link(session_id)
  #   # CoopHelperSup.start_coop_client(session_id)
  #   {:noreply, state}
  # end

  # def handle_info({:tts_pcm, pcm}, state) do
  #   IO.puts("Received  pcm: #{inspect(byte_size(pcm))}")
  #   {:ok, opus} = SockWorkstation.CodecNifGen.encode_pcm(state.session_id, pcm)
  #   IO.puts("Received opus: #{inspect(byte_size(opus))}")
  #   SockCoopClient.send_binary(state.coop_pid, opus)
  #   File.write!("peer.pcm", pcm, [:append])
  #   {:noreply, state}
  # end

  # def handle_info(:userid_invalid, state) do
  #     SockWorkstation.SockCoopClient.set_volume(state.coop_pid, 60)
  #     SockWorkstation.SockCoopClient.send_speaking(state.coop_pid)
  #     {:noreply, state}
  # end

  def handle_info(:tts_result, state) do
    # send(state.coop_mgr_pid, :run_sent_asr)
    # Process.send_after(state.coop_mgr_pid, :tts_stop, 200)
    # SockWorkstation.SockCoopClient.send_listening(state.coop_pid, state.session_id)

    {:noreply, state}
  end

  # 保活定时器回调
  def handle_info(:send_keepalive, state) do
    schedule_keepalive()
    {:noreply, state}
  end

  # def handle_info(:sup_shutdown, state) do
  #   children = DynamicSupervisor.which_children(CoopHelperSup) |> Enum.reverse()

  #   # 先停止所有子进程
  #   Enum.each(children, fn {_, pid, _, _} ->
  #     GenServer.stop(pid, :normal, 2000)
  #   end)

  #   {:stop, :normal, state}
  # end

  @impl true
  def terminate(_reason, state) do
    # IO.puts("coop mgr terminate: #{inspect(reason)}")
    CtrlMgrGen.rm_uid(state.session_id)
    :ok
  end

  defp schedule_keepalive() do
    Process.send_after(self(), :send_keepalive, @keepalive_interval)
  end

  defp via_tuple(session_id, type) do
    {:via, Registry, {SockWorkstation.SessionRegistry, {session_id, type}}}
  end
end

# if user_id == nil,
#   do:
#     Process.send_after(
#       coop_mgr.tts_helper_pid,
#       {:run_test_opus, "greet_authcode", "1150", "hello-1150"},
#       35000
#     )

# def handle_cast(:rm_asr_pid, state) do
#   {:noreply, %CoopMgrGen{state | asr_pid: nil}}
# end

# def handle_cast(:rm_tts_pid, state) do
#   {:noreply, %CoopMgrGen{state | tts_pid: nil}}
# end

# def handle_cast({:add_tts_pid, pid}, state) do
#   {:noreply, %CoopMgrGen{state | tts_pid: pid}}
# end

# def handle_info(:run_coop_client, state) when is_pid(state.coop_pid) do
#   {:noreply, state}
# end

# def handle_info({:run_coop_client, asr_helper_pid}, state) do
#   # send(state.coop_mgr_pid, :run_sent_asr)
#  CoopHelperSup.start_coop_client({state.session_id, asr_helper_pid})
#   # {:ok, coop_pid}=
#     # SockWorkstation.SockCoopClient.start_link({state.session_id, state.coop_mgr_pid})
#   # send(state.coop_mgr_pid, {:run_codec, coop_pid})

#   {:noreply, state}
# end

# def handle_info({:asr_result, result}, state) do
#   IO.puts("coop Received asr result: #{result}")
#   IO.inspect(state)
#   # SockWorkstation.SockASRClient.send_finish_task(state.asr_pid, state.asr_task_id)
#   send(state.asr_helper_pid, :asr_stop)

#   # send(state.coop_mgr_pid, {:run_sent_tts, result})
#   Process.send_after(state.coop_mgr_pid, :asr_stop, 200)

#   # text = "nihao"
#   # Process.sleep(1000)
#   # text = "nihao"
#   # SockWorkstation.SockTTSClient.send_tts_task(state.tts_pid, state.tts_task_id, text)

#   # # state =
#   #   state
#   #   # |> Map.delete(:asr_pid)
#   #   |> Map.delete(:asr_task_id)
#   # state =
#   #   state
#   #    |> Map.put(:asr_task_id,"")

#   {:noreply, state}
# end

# def handle_info(:asr_stop, state) do
#   SockWorkstation.SockASRClient.send_finish_task(state.asr_pid, state.asr_task_id)

#   state =
#     state
#     |> Map.put(:asr_task_id, "")

#   {:noreply, state}
# end

# def handle_info(:tts_stop, state) do
#   # SockWorkstation.SockTTSClient.send_finish_task(state.tts_pid, state.tts_task_id)

#   state =
#     state
#     # |> Map.delete(:tts_pid)
#     |> Map.put(:tts_task_id, "")

#   {:noreply, state}
# end

# def handle_info({:run_codec, coop_pid}, state) do
#   # Process.sleep(2000)
#   # CoopHelperSup.start_opus_decode({state["session_id"], state["self_pid"]})
#   CoopHelperSup.start_pcm_encode({state.session_id, coop_pid})
#   {:noreply, state}
# end

# def handle_info(:run_nif_codec, state) do
#   # Process.sleep(2000)
#   CoopHelperSup.start_nif_codec(state.session_id)
#   {:noreply, state}
# end

# def handle_info(:run_asr_helper, state) do
#   {:ok,asr_helper_pid}=CoopHelperSup.start_asr_helper(state.session_id)
#   send(state.coop_mgr_pid, {:run_coop_client, asr_helper_pid})
#   {:noreply, state|>Map.put(:asr_helper_pid, asr_helper_pid)}
# end

# def handle_info({:run_sent_tts, text}, state) do
#   # SockWorkstation.SockCoopClient.send_speaking(state.coop_pid)

#   {:ok, tts_pid} =
#     CoopHelperSup.start_tts_client({state.session_id, state.topus_pid})

#   Process.sleep(100)
#   SockWorkstation.SockCoopClient.set_volume(state.coop_pid, 60)
#   tts_task_id = UUID.uuid4(:hex)
#   SockWorkstation.SockTTSClient.send_run_task(tts_pid, tts_task_id)
#   # Process.sleep(80)
#   Process.sleep(500)
#   text = text
#   SockWorkstation.SockTTSClient.send_tts_task(tts_pid, tts_task_id, text)
#   Process.sleep(500)
#   SockWorkstation.SockTTSClient.send_finish_task(tts_pid, tts_task_id)

#   # {:noreply, state}
#   state =
#     state
#     |> Map.put(:tts_pid, tts_pid)
#     |> Map.put(:tts_task_id, tts_task_id)

#   {:noreply, state}
# end

# def handle_info(:run_sent_asr, state) do
#   # SockWorkstation.SockCoopClient.send_listening(state["self_pid"])

#   {:ok, asr_pid} =
#     CoopHelperSup.start_asr_client({state.session_id, state.coop_mgr_pid})

#   send(state.asr_helper_pid, {:asr_starting, asr_pid})

#   # if state.is_inited == false, do: SockWorkstation.SockCoopClient.send_listening(state.coop_pid)
#   asr_task_id = UUID.uuid4(:hex)
#   Process.sleep(80)
#   SockWorkstation.SockASRClient.send_run_task(asr_pid, asr_task_id)
#   Process.sleep(200)
#   send(state.asr_helper_pid, :asr_started)
#   # if Map.has_key?(state, :tts_task_id) do
#   #   SockWorkstation.SockTTSClient.send_finish_task(state.tts_pid, state.tts_task_id)
#   # end
#   state =
#     state
#     |> Map.put(:asr_pid, asr_pid)
#     |> Map.put(:asr_task_id, asr_task_id)

#   # |> Map.put(:is_inited, false)

#   # |> Map.delete(:tts_task_id)
#   {:noreply, state}
# end

# def handle_info({:recv_opus, opus}, state) do
#   # send(state.coop_mgr_pid, :run_sent_asr)
#   {:ok, pcm_data} = SockWorkstation.CodecNifGen.decode_opus(state.session_id, opus)
#   #  IO.puts("Received coop client info pcm: #{inspect(byte_size(data))}")
#   # SockWorkstation.OpusDecoderGen.opus_to_pcm(state["session_id"],data)
#   # File.write!("peer.pcm", pcm_data, [:append])
#   SockWorkstation.SockASRClient.send_asr_task(state.asr_pid, pcm_data)
#   # SockCoopClient.send_binary(state.coop_pid, opus)
#   # SockWorkstation.SockCoopClient.send_listening(state.coop_pid)

#   {:noreply, state}
# end

# def handle_info({:test_opus, opus}, state) do
#   SockCoopClient.send_binary(state.coop_pid, opus)
#   {:noreply, state}
# end

# def handle_info(msg, state) do
# IO.inspect msg
# {:noreply, state}
# end

# def handle_info(:run_asr_task, state) do
#   task_id=UUID.uuid4(:hex)
#   SockWorkstation.SockASRClient.send_run_task(state.asr_pid, task_id)
#   {:noreply, state}
# end

# def run_coop_client(session_id) do
#   GenServer.cast(via_tuple(session_id, "coop"), :run_coop_client)
# end

# def start_run_asr(session_id) do
#   GenServer.cast(via_tuple(session_id, "coop"), :start_run_asr)
# end

# def send_speaking(pid) do
#   send(pid, :run_sent_tts)
# end

# def send_listening(pid) do
#   send(pid, :run_sent_asr)
# end

# def handle_info(:run_sent_asr, state) do
#   SockWorkstation.SockCoopClient.send_listening(state.coop_pid)
#   {:ok, asr_pid} = CoopHelperSup.start_asr_client({state.session_id, state.coop_pid})
#   Process.sleep(80)
#   SockWorkstation.SockASRClient.send_run_task(asr_pid,  UUID.uuid4())
#   {:noreply, state}
# end

# def handle_cast(:run_coop_client, state) do
#   # CoopHelperSup.start_coop_client(state.session_id, state.coop_mgr_pid)
#   SockWorkstation.SockCoopClient.start_link(state.session_id, state.coop_mgr_pid)
#   {:noreply, state}
# end

# def handle_cast(:start_run_asr, state) do
#   CoopHelperSup.start_asr_client({state.session_id, state.coop_mgr_pid})
#   Process.send_after(self(), :run_asr_task, 80)
#   {:noreply, state}
# end

# def handle_cast({:start_opus_de, {session_id, pid}}, state) do
#   # {:ok, _pid} = OpusCodec.start_link()
#   CoopHelperSup.start_opus_decode({session_id, pid})
#   {:noreply, state}
# end

# def handle_cast({:start_pcm_en, {session_id, pid}}, state) do
#   CoopHelperSup.start_pcm_encode({session_id, pid})
#   {:noreply, state}
# end

# def handle_info(:start_coop_client, state) do

#   # case CoopHelperSup.start_coop_client(state.session_id) do
#   #   {:ok, _pid} ->

#   #     # CoopMgrGen.start_opus_decoder(state.session_id,state.coop_pid)
#   #     # CoopMgrGen.start_pcm_encoder(state.session_id, state.coop_pid)

#   #     IO.puts("start coop mgr success")

#   #   {:error, {:already_started, pid}} ->
#   #     add_coop_pid(state.session_id, pid)
#   #     # DynamicSupervisor.terminate_child( CoopHelperSup, pid)
#   #     # CoopHelperSup.start_coop_client(state.session_id)

#   #   {:error, _reason} ->
#   #     IO.puts("start coop client failed")
#   # end
#   CoopHelperSup.start_coop_client(state.session_id)

#   {:noreply, state}
# end

# def start_codec(session_id, pid) do
#   # Process.sleep(100)
#   CoopHelperSup.start_opus_decode({session_id, pid})
#   CoopHelperSup.start_pcm_encode({session_id, pid})
#   # start_pcm_encoder(session_id, pid)
#   # start_opus_decoder(session_id, pid)

#   # GenServer.cast(@name, {:start_codec, {session_id, pid}})
# end

# def start_pcm_encoder(session_id, pid) do
#   GenServer.cast(via_tuple(session_id, "coop"), {:start_pcm_en, {session_id, pid}})
# end

# def start_opus_decoder(session_id, pid) do
#   GenServer.cast(via_tuple(session_id, "coop"), {:start_opus_de, {session_id, pid}})
# end

# def start_coop_client(session_id) do
#   GenServer.cast(via_tuple(session_id, "coop"), {:start_coop_client, session_id})
# end

# def start_asr_client(session_id, pid) do
#   GenServer.cast(via_tuple(session_id, "coop"), {:start_asr_client, {session_id, pid}})
# end

# def start_tts_client(session_id, pid) do
#   GenServer.cast(via_tuple(session_id, "coop"), {:start_tts_client, {session_id, pid}})
# end

# def run_asr() do
#   user_id = "test"
#   session_id = SockWorkstation.CtrlMgrGen.get_state()[user_id]
#   coop_pid = SockWorkstation.CoopMgrGen.get_state(session_id).coop_pid
#   SockWorkstation.SockCoopClient.send_listening(coop_pid)
#   # CoopHelperSup.start_pcm_encode({session_id, coop_pid})
#   # topus_pid=SockWorkstation.CoopMgrGen.get_state(session_id).topus_pid
#   # SockWorkstation.CoopMgrGen.start_tts_client(session_id,topus_pid)
#   # tts_pid=SockWorkstation.CoopMgrGen.get_state(session_id).tts_pid
#   topcm_pid = SockWorkstation.CoopMgrGen.get_state(session_id).topcm_pid
#   SockWorkstation.CoopMgrGen.start_asr_client(session_id, topcm_pid)
#   asr_pid = SockWorkstation.CoopMgrGen.get_state(session_id).asr_pid

#   # task_id = UUID.uuid4()
#   # SockWorkstation.SockASRClient.send_run_task(asr_pid, task_id)
#   # SockWorkstation.SockASRClient.send_asr_task(asr_pid, pcm_data)
#   # SockWorkstation.SockTTSClient.send_run_task(tts_pid, task_id)
#   # SockWorkstation.SockTTSClient.send_tts_task(tts_pid, task_id, text)
#   # Process.sleep(1000)
#   # SockWorkstation.SockASRClient.send_finish_task(asr_pid, task_id)
#   # SockWorkstation.SockCoopClient.sent_speaking(coop_pid)
# end

# {:ok, _pid} =
#   CoopHelperSup.start_tts_client(
#     {CoopMgrGen.get_state().topus_pid, "session_id"}
#   )

# pid = CoopMgrGen.get_state().tts_pid
# task_id = UUID.uuid4()
# send_run_task(pid, task_id)
# split_by_punctuation(texts)
# |> Enum.each(fn text ->
# Process.sleep(200)
# send_tts_task(pid, task_id, text)

# end)
# send_finish_task(pid, task_id)
# SockWorkstation.SockCoopClient.sent_listening(CoopMgrGen.get_state().coop_pid)

# def handle_call(:get_coop_pid, _from, state) do
#   # case Map.get(state, session_id, "coop_pid") do
#   #   %{"coop_pid" => coop_pid} -> {:reply, coop_pid, state}
#   #   _ -> {:reply, nil, state}
#   # end
#   {:reply, state.coop_pid, state}
# end

# def handle_cast({:start_codec, {session_id, pid}}, state) do
#   Process.sleep(2000)
#   start_pcm_encoder(session_id, pid)
#   start_opus_decoder(session_id, pid)

#   {:noreply, state}
# end

# def get_coop_pid(session_id) do
#   GenServer.call(via_tuple(session_id, "coop"), {:get_coop_pid, session_id})
# end

# def rm_coop_pid(session_id) do
#   GenServer.call(@name, {:rm_coop_pid, session_id})
# end

# def add_session_id(session_id) do
#   GenServer.cast(@name, {:add_session_id, session_id})
# end

# def handle_cast({:start_coop_client, session_id}, state) do
#   CoopHelperSup.start_coop_client(session_id)
#   {:noreply, state}
# end

# def handle_cast({:start_asr_client, {session_id, pid}}, state) do
#   {:ok, asr_pid} = CoopHelperSup.start_asr_client({session_id, pid})
#   {:noreply, %CoopMgrGen{state | asr_pid: asr_pid}}
# end

# def handle_cast({:start_tts_client, {session_id, pid}}, state) do
#   {:ok, tts_pid} = CoopHelperSup.start_tts_client({session_id, pid})
#   {:noreply, %CoopMgrGen{state | tts_pid: tts_pid}}
#   # {:noreply, state}
# end
